home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / programr / appsrcs.zip / APPBAR.ZIP / APPBAR.C < prev    next >
C/C++ Source or Header  |  1993-06-10  |  17KB  |  464 lines

  1. /*-------------------------------------------------------------------------
  2.  AppBar.c
  3.  
  4.  A buttonbar to launch applications from.
  5.  
  6.  by
  7.  GMP van kempen
  8.  NEVERnever Software 1991-1993
  9.  
  10. history:
  11.     0.xx    tryout versions
  12.     3.1     first serious version, added move option,
  13.         use of ini-file.
  14.     3.14    added QuickView
  15.     3.141   improved fool-proofness, added toggle start/close
  16.         an application, second button now terminates Windows.
  17.         first released version.
  18.     3.1415  added greyed buttons when a program is active, improved
  19.         the looks of appbar. Nicer aboutbox.
  20.         Exit option built-in. Made use of Columns possible
  21.         and increased maximum number of buttons up to 24.
  22.     3.1415a For closing a program now using WM_CLOSE instead of
  23.         WM_DESTROY. Adding possibility to specify a StartDirectory.
  24.     3.1415b Added option to skip the closing feature.
  25.     3.1415c Changed the way a HWND of a started programs was got.
  26.         Changed initialization of IcoFileName, ProgFileName, StartDir.
  27.     3.14159 Upgraded to Win3.1. Changed redrawing code for icons.
  28.         Added Setup program. Added Restart Option. Fixed bug
  29.         in startDir function: current drive is also changed.
  30.         Added click or DoubleClick mode. Added Start normal, maximized or
  31.         minimized. Increased maximum buttons to 32.
  32.         Load= and Run= statements in win.ini are supported when
  33.         AppBar is shell. StayInFront option is added. Changed Aboutbox.
  34.         Improved StayInfront. Skipped close option for all *.com and *.pif
  35.         files. Start AppSetup when appbar not initialized. Changed ini-file format.
  36.         Changed the looks of exitWindows Dialog window.
  37. APPBAR_NEW
  38.     for Windows 3.1
  39.     3.20    Source ported to Windows 3.1. Uses ExtractIcon getting the Icon
  40.         from a file. Displaying with DrawIcon. Added DropFile function.
  41.         Added Sound. Made Dialog Boxes resolution independent. Fixed dialog
  42.         EndPaint bugs. Improved Close function by checking if AppBar
  43.         is shell. Fixed redraw button problem. Used a timer to check
  44.         program states regularly. When AppBar is Shell, the Close button
  45.         will Exit Windows. The groupfile specified by ShellGroup= will
  46.         be executed when AppBar is Shell.
  47.     3.30    made drop of multiple files possible. If Shell, AppBar won't
  48.         launch itself when it is also specified in load=, run= or ShellGroup.
  49.         Use ShellExecute instead of WinExec. Now possible to specify
  50.         Datafiles and StartUpParameters. Added QuickLoad Option.
  51.         Max Buttons = 48. Added Run Option. Start ShellGroup programs
  52.         minimized. Improved closefunction by subclassing closing window,
  53.         (Thanks to Erkki Riekkola). Bug fixed in max-columns, is now
  54.         MAXBUTTONS, was MAXAPPS. Added maxsize option. Added save option
  55.         to move button. Removed IsDosExe(), rely on IsDosWindow() now.
  56.         Made AppBar restartable when it is Shell. Also will it execute
  57.         the options given to win.com when it is shell. Made Shellcheck
  58.         on "appbar.exe" case insensitive. Use Shellexecute in IsShell()
  59.         when executing load= & run= lines. If Buttons % Rows isn't zero,
  60.         add Buttons up till it is. Added WM_APPBAR_RESTART message. Added
  61.         minimize button.
  62.     4.00    - Made use of ctl3D.dll for 3D looks on dialog boxes.
  63.         - Changed clicking mode:
  64.           MOUSE_CLICK:        launch program, if NOTALIVE
  65.                     bring to from, if still ALIVE
  66.           MOUSE_DOUBLECLICK:    kill program if ALIVE
  67.           (double_click option is abandonned)
  68.         - Fixed ALT-F4 bug: AppBar will exit windows if it is shell and
  69.           ALT-F4 is pressed.
  70.         - Improved the executing of groupfiles. (but ShellGroup now only
  71.           accepts one groupfile!)
  72.         - Added RestartWindows option to ExitWindows Dialog.
  73.         - Added simple keyboard interface:
  74.           ESCAPE:       toggles between keyboard interface on/off
  75.           ENTER:       is MOUSE_CLICK on current button
  76.           DELETE:       is MOUSE_DOUBLECLICK on current button
  77.           UP ARROW:    move current button 1 up
  78.           DOWN ARROW:  move current button 1 down
  79.         - Added Help system.
  80.         - Added optional multiple systembuttons. Not only exit button,
  81.           but run button also. (If AppBar is shell, the exit button will
  82.           always be included)
  83.         - Improved error messages.
  84.         - added NoSound option. AppBar will not play the program-start sound
  85.           if this option is chosen.
  86.         - restored Doubleclick option
  87.         - Added BigButtons & borders
  88.         - Moved Run button to separate App.
  89.         (4.00.4)
  90.         - fixed a bug with the exit button, it will now always be shown
  91.           if AppBar is shell, even if no Exit Button is selected.
  92.         - fixed problem with dropping files and bordersize.
  93.         - fixed bug with updating closed programs (CheckProgramStatus())
  94.         - added a StayInFront toggle button to the systembuttons.
  95.         - fixed bug that AppBar only closes and not exit Windows when
  96.           it is shell and restarted.
  97.         - removed Exit Button, and made it a separate App.
  98.         (4.00.5)
  99.         - fixed a bug in reading minimized bit in groupfiles (thanks
  100.           to Andy Jacobs).
  101.         - Made "NoSound" also work on dropped files.
  102.         - removed QuickExit option for the removed Exit Button.
  103.         - moved some functions to APPLIB.DLL
  104.         (4.00.6)
  105.         - moved IsAppBarShell back from applib.dll to appbar.exe
  106.         - changed ReadButtonIni and SvaButtonIni functions
  107.         - improved value checking of AppSystem.Top & AppSystem.Left
  108.         - significantly improved the communication speed of AppBar and
  109.           Tip, by dropping more then one filename at the time.
  110.         - fixed a bug with Notepad when dropping extensionless files, by
  111.           adding a dot to the filename.
  112.  
  113. ---------------------------------------------------------------------------*/
  114.  
  115. //compile with the strictest error checking
  116. #define STRICT
  117. #include <windows.h>
  118. #include <windowsx.h>
  119. #include <shellapi.h>
  120. #include <string.h>
  121. #include <stdio.h>
  122. #include <ctl3d.h>
  123. #include <memory.h>
  124. #include "appbar.h"
  125.  
  126. #define MAKECHILD(a,b,c,d,e,f,g,h) CreateWindow(a,b,WS_CHILD | WS_VISIBLE | c,d,e,f,g,hWnd,h,hInst,(LPSTR) NULL)
  127. #define MAKEBUTTON(a,b,c,d,e,f)       MAKECHILD("button",a,BS_PUSHBUTTON | BS_OWNERDRAW,b,c,d,e,f)
  128. #define MAKESTATIC(a,b,c,d)       MAKECHILD("static",NULL,SS_BLACKRECT,a,b,c,d,(HMENU)-1)
  129. #define MAKEBORDER(a,b,c,d)       MAKECHILD("static",NULL,SS_WHITERECT,a,b,c,d,(HMENU) -1)
  130.  
  131. APPBARBUTTONS     AppButton[MAXAPPS], AppEmptyButton;
  132. APPSYSTEM     AppSystem;
  133. APPSOUND     AppSound;
  134. APPWINDOW     AppWindow = {1, MAXBUTTONS, 32, 32};
  135. APPMAXSIZE     AppMaxSize;
  136. char         szAppName[] = "AppBar";
  137. int         iCurrent = 0, iActive = 0, iKey = 1;
  138. int         cxChar, cyChar, iShuffledButton, FirstAppButton = 1;
  139. HWND         hWndMain, hWndButton[MAXBUTTONS], hWndCurrentButton;
  140. HINSTANCE     hInst, hPrevInst;
  141. HBITMAP         hAppLogo, hNNever, hbBlank, hbKeyb;
  142. HBITMAP      hbPressed;
  143. HICON         hSystem, hBlank, hPressed, hQuickLoad, hKeybOn;
  144. HICON         hPressed2, hSystem2;
  145. LPDRAWITEMSTRUCT lpIconDIS;
  146. BOOL         bQuickLoad = FALSE, bMoveButton = FALSE;
  147. BOOL         bKeyboardOn = FALSE, bExecuteProg = TRUE, bShuffleButton = FALSE;
  148. short         Rows, xSize, ySize;
  149.  
  150.  
  151. int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  152.            LPSTR lpszCmdLine, int nCmdShow)
  153.     {
  154.     HWND    hWnd;
  155.     MSG     msg;
  156.     WNDCLASS    wndclass;
  157.     short    xScreen, yScreen;
  158.  
  159.     if(!hPrevInstance)
  160.     {
  161.     wndclass.style            = CS_HREDRAW | CS_VREDRAW;
  162.     wndclass.lpfnWndProc        = WndProc;
  163.     wndclass.cbClsExtra        = 0;
  164.     wndclass.cbWndExtra        = 0;
  165.     wndclass.hInstance        = hInstance;
  166.     wndclass.hIcon            = LoadIcon(hInstance, MAKEINTRESOURCE(1000));
  167.     wndclass.hCursor        = LoadCursor(NULL, IDC_ARROW);
  168.     wndclass.hbrBackground        = GetStockBrush(LTGRAY_BRUSH);
  169.     wndclass.lpszMenuName        = NULL;
  170.     wndclass.lpszClassName        = szAppName;
  171.  
  172.     RegisterClass(&wndclass);
  173.     }
  174.  
  175.     SetCursor(LoadCursor(NULL, IDC_WAIT));
  176.  
  177.     hInst = hInstance;
  178.     hPrevInst = hPrevInstance;
  179.  
  180.     Ctl3dRegister(hInst);
  181.     Ctl3dAutoSubclass(hInst);
  182.  
  183.     // read the settings from AppBar.ini
  184.     IniRead();
  185.  
  186.     if(AppSystem.BigButtons)
  187.     AppWindow.cxButton = AppWindow.cyButton = 38;
  188.  
  189.     LoadAppBarResources();
  190.  
  191.     // if AppBar is Shell, execute the load=, run=, startup groupfiles
  192.     // and cmdline parameters given to win.com (at start of Windows)
  193.     // only at the first instance of AppBar.
  194.     if(!hPrevInstance)
  195.     {
  196.     if(IsAppBarShell())
  197.         {
  198.         WinExec(lpszCmdLine, SW_SHOWNORMAL);
  199.         DoShellTasks();
  200.         }
  201.     }
  202.  
  203.     AppWindow.nButtons = AppSystem.Buttons+FirstAppButton;
  204.     AppWindow.nColumns = AppSystem.Columns;
  205.  
  206.     // try to add enough buttons to fill all the columns
  207.     while(AppWindow.nButtons % AppWindow.nColumns)
  208.     {
  209.     AppWindow.nButtons++;
  210.     if(AppWindow.nButtons > MAXAPPS)
  211.         break;
  212.     }
  213.     if(AppWindow.nButtons % AppWindow.nColumns)
  214.     {
  215.     AppWindow.nButtons = AppSystem.Buttons+FirstAppButton;
  216.     AppWindow.nColumns = 1;
  217.     }
  218.  
  219.     AppMaxSize = CalculateAppMaxSize();
  220.  
  221.     if(AppSystem.Left == -1) // -1 is default, right top of the screen.
  222.     {
  223.     xScreen = GetSystemMetrics(SM_CXSCREEN) - AppSystem.Border;
  224.     xScreen -= (AppWindow.cxButton+AppSystem.Border)*AppWindow.nColumns;
  225.     }
  226.     else
  227.     xScreen = AppSystem.Left;
  228.     if(AppSystem.Top == -1)
  229.     yScreen = 0;
  230.     else
  231.     yScreen = AppSystem.Top;
  232.  
  233.     Rows = AppWindow.nButtons/AppWindow.nColumns;
  234.     xSize = AppWindow.cxButton*AppWindow.nColumns;
  235.     xSize += (AppWindow.nColumns+1)*AppSystem.Border;
  236.     ySize = AppWindow.cyButton*Rows + (Rows+1)*AppSystem.Border;
  237.  
  238.     hWnd = CreateWindow(szAppName, "AppBar 4.0",
  239.             WS_POPUP | WS_VISIBLE,
  240.             xScreen, yScreen, xSize, ySize,
  241.             NULL, NULL, hInstance,NULL);
  242.  
  243.     hWndMain = hWnd;
  244.     SetTimer(hWnd, ID_TIMER, 1000, NULL);
  245.     SetCursor(LoadCursor(NULL, IDC_ARROW));
  246.     ShowWindow(hWnd, SW_SHOWNORMAL);
  247.     UpdateWindow(hWnd);
  248.  
  249.     while(GetMessage(&msg, NULL, 0, 0))
  250.     {
  251.     TranslateMessage(&msg);
  252.     DispatchMessage(&msg);
  253.     }
  254.  
  255.     Ctl3dUnregister(hInst);
  256.     return msg.wParam;
  257.     } /* end WinMain */
  258.  
  259. /*------------------------------------------------------------------------/
  260.    FUNCTION: WndProc()
  261. /------------------------------------------------------------------------*/
  262. long WINAPI WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  263.     {
  264.     static DLGPROC lpfnSystemDlgProc;
  265.     static HICON   hIcon[MAXAPPS];
  266.     TEXTMETRIC       tm;
  267.     HBRUSH       hbrush;
  268.     int        i, xPos, yPos;
  269.  
  270.     switch (message)
  271.     {
  272.     case WM_CREATE:
  273.         if(AppSystem.Initialized < APPBARVERSION)
  274.         if(WinExec("AppSetup.exe",SW_SHOWNORMAL) >= 32)
  275.             SendMessage(hWnd, WM_DESTROY, 0, 0);
  276.         tm = RetrieveTextMetrics(hWnd);
  277.         cxChar = tm.tmAveCharWidth;
  278.         cyChar = tm.tmHeight;
  279.         if(AppSystem.Border)
  280.         Ctl3dSubclassCtl(MAKEBORDER(0, 0, xSize, ySize));
  281.         for(i=0;i<AppWindow.nButtons;i++)
  282.         {
  283.         xPos=AppSystem.Border+(AppSystem.Border+AppWindow.cxButton)*(i/(AppWindow.nButtons/AppWindow.nColumns));
  284.         yPos=AppSystem.Border+(AppSystem.Border+AppWindow.cyButton)*(i%(AppWindow.nButtons/AppWindow.nColumns));
  285.         if(AppSystem.Border)
  286.             Ctl3dSubclassCtl(MAKESTATIC(xPos-1, yPos-1,
  287.                 AppWindow.cxButton+2, AppWindow.cyButton+2));
  288.         hWndButton[i] = MAKEBUTTON(NULL, xPos, yPos,
  289.                 AppWindow.cxButton, AppWindow.cyButton,
  290.                 ID_BUTTON1+i);
  291.         }
  292.         LoadAllButtonIcons(hIcon);
  293.         SetNormalChildCursor();
  294.         DragAcceptFiles(hWnd, TRUE);
  295.         InitTip();
  296.         if(AppSound.EnableSound != 0)
  297.         if(stricmp(AppSound.AppBarStart, "<none>") != 0)
  298.             sndPlaySound(AppSound.AppBarStart, SND_ASYNC | SND_NODEFAULT);
  299.         return 0;
  300.  
  301.     case WM_SYSCOLORCHANGE:
  302.         Ctl3dColorChange();
  303.         return 0;
  304.  
  305.     case WM_CTLCOLOR:
  306.         hbrush = Ctl3dCtlColorEx(message, wParam, lParam);
  307.         if(hbrush != (HBRUSH) FALSE)
  308.         return hbrush;
  309.         else
  310.         return DefWindowProc(hWnd, message, wParam, lParam);
  311.  
  312.     case WM_SYSCHAR:
  313.     case WM_SYSKEYUP:
  314.         return 0;
  315.  
  316.     case WM_SYSKEYDOWN:
  317.         return ProcessSystemKeys((int) wParam);
  318.  
  319.     case WM_KEYDOWN:
  320.         return KeyboardInterface((int)wParam);
  321.  
  322.     case WM_DRAWITEM:
  323.         DrawItem((LPDRAWITEMSTRUCT)lParam, hIcon);
  324.         return 0;
  325.  
  326.     case WM_TIMER:
  327.         CheckProgStatus();
  328.         if(AppSystem.StayInFront == 1 && GetActiveWindow() != hWndMain)
  329.         SetWindowPos(hWnd, NULL, 0, 0, 0, 0,
  330.                  SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
  331.         return 0;
  332.  
  333.     case WM_COMMAND:
  334.          // If a button was clicked, then it is the currently selected tool.
  335.         if(HIWORD(lParam) == BN_CLICKED || HIWORD(lParam) == BN_DOUBLECLICKED)
  336.         {
  337.         if((wParam >= (UINT) ID_BUTTON1) && (wParam <= (UINT) (ID_BUTTON1 + AppWindow.nButtons)))
  338.             {
  339.             iCurrent = 0;
  340.             while((ID_BUTTON1 + iCurrent) != (int) wParam)
  341.             iCurrent++; // just increment i !!
  342.             iKey = iCurrent; // sync keyb interface with mouse click
  343.             if(iCurrent < FirstAppButton)
  344.             {
  345.             if((HIWORD(lParam) == BN_CLICKED && !AppSystem.DoubleClick) || (HIWORD(lParam) == BN_DOUBLECLICKED && AppSystem.DoubleClick))
  346.                 {
  347.                 if(iCurrent == SYSTEM_BUTTON)
  348.                 {
  349.                 lpfnSystemDlgProc = (DLGPROC) MakeProcInstance((FARPROC)SystemDlgProc, hInst);
  350.                 DialogBox(hInst, "SystemDlg", hWnd, lpfnSystemDlgProc);
  351.                 FreeProcInstance( (FARPROC) lpfnSystemDlgProc);
  352.                 break;
  353.                 }
  354.                 }
  355.             }
  356.             if(iCurrent >= FirstAppButton)
  357.             {
  358.             if(!bQuickLoad)
  359.                 {
  360.                 CheckProgStatus();
  361.                 StartOrCloseProgram(iCurrent-FirstAppButton, HIWORD(lParam)); // start and close programs linked to a button.
  362.                 }
  363.             else //QuickLoad is active
  364.                 {
  365.                 if(bShuffleButton)
  366.                 {
  367.                 bShuffleButton = FALSE;
  368.                 SetNormalChildCursor();
  369.                 AppButton[iCurrent-FirstAppButton] = AppButton[iShuffledButton-FirstAppButton];
  370.                 hIcon[iCurrent-FirstAppButton] = hIcon[iShuffledButton-FirstAppButton];
  371.                 SaveButtonIni(AppButton[iCurrent-FirstAppButton], iCurrent-FirstAppButton, (LPSTR) INI_BUTTON, (LPSTR) INI_FILE);
  372.                 InvalidateRect(hWndButton[iCurrent], NULL, TRUE);
  373.                 InvalidateRect(hWndButton[iShuffledButton], NULL, TRUE);
  374.                 UpdateWindow(hWnd);
  375.                 }
  376.                 else
  377.                 {
  378.                 bShuffleButton = TRUE;
  379.                 SetShuffleChildCursor();
  380.                 iShuffledButton = iCurrent;
  381.                 }
  382.                 }
  383.             }
  384.             }
  385.         }
  386.         if(wParam == WM_APPBAR_RESTART)
  387.         if(WinExec("AppBar.exe", SW_SHOWNORMAL) > 32)
  388.             PostMessage(hWndMain, WM_CLOSE, 0, 0);
  389.  
  390.         if(wParam == WM_APPBAR_CLOSE)
  391.         {
  392.         InvalidateRect(hWndButton[0], NULL, TRUE);
  393.         UpdateWindow(hWnd);
  394.         SendMessage(hWndMain, WM_DESTROY, 0, 0);
  395.         }
  396.  
  397.         if(wParam == PM_TIP_SETICON)
  398.         TipSetIcon((WORD) (lParam-1), hIcon);
  399.  
  400.         return 0;     /* end WM_COMMAND */
  401.  
  402.        case WM_DROPFILES:
  403.         ProcessDropFiles((HANDLE) wParam, hIcon);
  404.         return 0;
  405.  
  406.     case WM_LBUTTONDOWN:    // Allows moving of a whole window
  407.         SetCursor(LoadCursor(NULL, IDC_SIZE));
  408.         bMoveButton = TRUE;
  409.         return(DefWindowProc(hWnd, WM_NCLBUTTONDOWN, HTCAPTION, lParam));
  410.  
  411.     case WM_MOVE:
  412.         if(bMoveButton)
  413.         {
  414.         bMoveButton = FALSE;
  415.         if(MessageBox(NULL,"Save AppBar's new position","AppBar 4.0",MB_YESNO) ==IDYES)
  416.             {
  417.             /* horizontal position */
  418.             AppSystem.Left = (int) LOWORD(lParam);
  419.             /* vertical position */
  420.             AppSystem.Top = (int) HIWORD(lParam);
  421.             sprintf(szBuffer,"%d", AppSystem.Left);
  422.             WritePrivateProfileString(INI_SYSTEM, LEFT, szBuffer, INI_FILE);
  423.             sprintf(szBuffer,"%d", AppSystem.Top);
  424.             WritePrivateProfileString(INI_SYSTEM, TOP, szBuffer, INI_FILE);
  425.             }
  426.         }
  427.         return 0;
  428.  
  429.     case WM_ACTIVATEAPP:
  430.         if(wParam == 0)
  431.         if(GetActiveWindow() != NULL)
  432.             if(iActive != 0)
  433.             {
  434.             AppButton[iActive-1].hWndApp = GetActiveWindow();
  435.             if(AppButton[iActive-1].ShowMode == 3)
  436.                 SetWindowPos(AppButton[iActive-1].hWndApp,
  437.                      NULL,
  438.                      AppMaxSize.left,
  439.                      AppMaxSize.top,
  440.                      AppMaxSize.width,
  441.                      AppMaxSize.height,
  442.                      SWP_NOACTIVATE | SWP_NOZORDER);
  443.             if(AppButton[iActive-1].Close)
  444.                 AppButton[iActive-1].Close = !IsDosWindow(AppButton[iActive-1].hWndApp);
  445.             if(AppButton[iActive-1].Close)
  446.                 AppButton[iActive-1].ProgStatus = ALIVE;
  447.             else
  448.                 AppButton[iActive-1].ProgStatus = NOTALIVE;
  449.             iActive = 0;
  450.             InvalidateRect(hWndCurrentButton, (LPRECT) NULL, FALSE);
  451.             UpdateWindow(hWndCurrentButton);
  452.             }
  453.         return 0;
  454.  
  455.        case WM_DESTROY:    // kill the whole program
  456.         KillTimer(hWnd, ID_TIMER);
  457.         FreeAppBarResources();
  458.         DragAcceptFiles(hWnd, FALSE);
  459.         PostQuitMessage(0);
  460.         return 0;
  461.     }
  462.     return DefWindowProc(hWnd, message, wParam, lParam);
  463.     } /* end WndProc */
  464.